package priv.dajie.tzzq.core;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import priv.dajie.tzzq.bot.Bot;
import priv.dajie.tzzq.bot.BotManager;
import priv.dajie.tzzq.bot.buff.BuffBot;
import priv.dajie.tzzq.bot.c5.C5Bot;
import priv.dajie.tzzq.bot.exception.NetworkException;
import priv.dajie.tzzq.bot.exception.TakeBackException;
import priv.dajie.tzzq.bot.model.*;
import priv.dajie.tzzq.bot.steam.SteamBot;
import priv.dajie.tzzq.bot.steam.exception.SteamException;
import priv.dajie.tzzq.common.ApplicationContextUnit;
import priv.dajie.tzzq.model.GoodsState;
import priv.dajie.tzzq.model.TradeStateItem;
import priv.dajie.tzzq.model.TradeStateItems;
import priv.dajie.tzzq.service.SteamService;
import priv.dajie.tzzq.service.TradeService;
import priv.dajie.tzzq.spider.model.Platform;

import java.math.BigDecimal;
import java.util.*;

public class AutoSell implements Runnable {
    private BuffBot buffBot;
    private C5Bot c5Bot;
    private SteamBot steamBot;
    private Logger logger = LogManager.getLogger(this.getClass());
    private HashMap<String, SteamSellingItem> sellingIDMap;

    private SteamService steamService = ApplicationContextUnit.getInstance().getBean(SteamService.class);
    private TradeService tradeService = ApplicationContextUnit.getInstance().getBean(TradeService.class);

    {
        buffBot = BotManager.getBuffBot();
        c5Bot = BotManager.getC5Bot();
        steamBot = BotManager.getSteamBot();
    }


    private void c5TakeBack(TradeStateItems tradeStateItems){
        long searchHour = System.currentTimeMillis() - tradeStateItems.get(0).getBuyTime().getTime() + (long) (60 * 60 * 2 * 1000);
        BuyHistoryItems BuyHistorys = c5Bot.getBuyHistoryByTime(searchHour);
        HashMap<String, BuyHistoryItem> buyHistoryItemMap = BuyHistorys.getMap(); // 把购买历史转换为map
//        List<String> trackIds = new ArrayList<>();
        for(int i=0;i<tradeStateItems.size();i++){
            TradeStateItem tradeStateItem = tradeStateItems.get(i);
            BuyHistoryItem buyHistoryItem = buyHistoryItemMap.get(tradeStateItem.getBuyId());
            if(buyHistoryItem!= null) {
                if (buyHistoryItem.getTradeState() == TradeState.SUCCESS){
                    logger.info(tradeStateItem.getSteamName()+"已被取回！");
                    tradeService.updateState(tradeStateItem.getId(), GoodsState.PACKAGE);
                }
                else if(buyHistoryItem.getTradeState() == TradeState.FAIL){
                    tradeService.updateState(tradeStateItem.getId(), GoodsState.FAIL);

                }
            }
            else {
                logger.error(tradeStateItem.getSteamName()+"在"+searchHour+"小时内找不到记录");
            }
        }

    }

    public void takeBack(Platform platform) {
        Bot bot = platform == Platform.C5 ? c5Bot : buffBot;
        TradeStateItems tradeStateItems = tradeService.listTradeStateItem(GoodsState.WAIT, platform); // 获取待发货的商品
        if (platform == Platform.C5){
            TradeStateItems tradeStateTakeBackItems =tradeService.listTradeStateItem(GoodsState.TAKE_BACK, platform); // 获取待发货的商品
            if (tradeStateTakeBackItems.size()>0) {
                c5TakeBack(tradeStateTakeBackItems);
            }
        }
        if (tradeStateItems.size() == 0) {
            return;
        }
        long searchHour = System.currentTimeMillis() - tradeStateItems.get(0).getBuyTime().getTime() + (long) (60 * 60 * 2 * 1000);
        if (searchHour < 0) {
            throw new RuntimeException("搜索时间异常：" + searchHour);
        }
        logger.info("获取" + platform.toString() + "购买历史记录");
        BuyHistoryItems BuyHistorys = bot.getBuyHistoryByTime(searchHour); // 获取16小时历史购买记录 待优化 ： 当前时间 - 最早购买且没发货的商品的时间 + 3600*1000
        HashMap<String, BuyHistoryItem> buyHistoryItemMap = BuyHistorys.getMap(); // 把购买历史转换为map
        PackItems packItems = bot.getPack();
        HashMap<String, PackItem> packItemMap = packItems.getMap();
        List<PackItem> takeBackList = new ArrayList<>(); // 待取回商品的列表
        HashMap<String, TradeStateItem> tradeStateItemHashMap = new HashMap<>();
        SteamPackItems steamPackItems = null;
        HashMap<String, SteamPackItem> packMap = null;
        for (TradeStateItem tradeStateItem : tradeStateItems) { // 在交易记录中判断每一个商品是否可以取回
            BuyHistoryItem buyHistoryItem = buyHistoryItemMap.get(tradeStateItem.getBuyId());
            if (buyHistoryItem == null) { // 判断购买记录是否存在
                logger.error(tradeStateItem.getSteamName() + " " + tradeStateItem.getBuyId() + "：在" + searchHour / 1000 + "小时的购买历史中在找不到记录");
            } else if (buyHistoryItem.getTradeState() == TradeState.SUCCESS) {
                PackItem takeBackItem = packItemMap.get(tradeStateItem.getSteamName()); // 获取取回的商品
                if (takeBackItem != null) {
                    tradeStateItemHashMap.put(tradeStateItem.getSteamName(), tradeStateItem);
                    logger.info(platform.toString() + " " + takeBackItem + " 已发货");
                    takeBackList.add(takeBackItem); // 把背包物品添加至取回列表
                }
                else {
                    logger.error(platform.toString() + "背包找不到商品：" + buyHistoryItem.getQualityName());
                    // 获取steam背包数据
                    if (steamPackItems == null) {
                        steamPackItems = steamBot.getPack();
                        packMap = steamPackItems.getMap();
                    }
                    if(packMap.get(tradeStateItem.getSteamName())!=null){
                        tradeService.updateState(tradeStateItem.getId(), GoodsState.PACKAGE);
                        logger.info(tradeStateItem.getSteamName()+"背包中找到商品，状态更新为：待上架");

                    }
                }
            } else if (buyHistoryItem.getTradeState() == TradeState.FAIL) {
                tradeService.updateState(tradeStateItem.getId(), GoodsState.FAIL, new BigDecimal(0));
                logger.info(platform.toString() + " " + buyHistoryItem.getQualityName() + " 已失效");
            } else if (buyHistoryItem.getTradeState() == TradeState.OTHER) {
                logger.error(platform.toString() + "历史购买存在未知状态：" + buyHistoryItem);
            }

        }
        logger.info(platform.toString() + "开始取回商品");
        for (int i = 0; i < takeBackList.size(); i += 5) { // 开始取回商品
            while (bot.isTrading()) { // 判断是否存在交易
                logger.info("等待" + platform.toString() + "交易完成");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            int max = Math.min(i + 5, takeBackList.size());
            String[] steamTradeItems;
            try {
                steamTradeItems = bot.autoTakeBack(takeBackList.subList(i, max)); // 发送报价
                logger.info(platform.toString() + "发送了" + steamTradeItems.length + "报价：" + Arrays.toString(steamTradeItems));
            } catch (TakeBackException e) {
                e.printStackTrace();
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                continue;
            }
            if (steamTradeItems.length == 0) {
                continue;
            }
            List<String> takeBackSteamName = steamTrade(steamTradeItems); // steam接收报价
            logger.info("取回"+takeBackSteamName.size()+"个物品");
            for (String steamName : takeBackSteamName) {
                logger.info(steamName + "：取回成功");
                tradeService.updateState(tradeStateItemHashMap.get(steamName).getId(), GoodsState.PACKAGE, new BigDecimal(0)); // 取回成功的商品设置为待上架
            }

        }
    }

    public List<String> steamTrade(String[] ids) {
        ArrayList<String> steamNames = new ArrayList<>();
        for (String id : ids) {
            String tradeid = steamBot.trade(id);
            if (tradeid == null) {
                continue;
            }
            List<String> steamNameTemp = steamBot.getTradeItems(tradeid);
            steamNames.addAll(steamNameTemp);
        }
        return steamNames;
    }

    public void steamSell() {
        // 获取待上架的商品
        TradeStateItems tradeStateItems = tradeService.listTradeStateItem(GoodsState.PACKAGE);
        SteamPackItems steamPackItems;
        int error = 0;
        while (true) {
            try {
                // 获取steam背包
                steamPackItems = steamBot.getPack();
            } catch (NetworkException e) {
                logger.error(e);
                if (error > 5) {
                    throw new SteamException("获取背包失败");
                }
                try {
                    Thread.sleep(1000 * ++error);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                continue;
            }
            if (steamPackItems.size() == 0) {
                logger.error("获取steam背包返回数据为空");
                continue;
            }
            break;
        }
        HashMap<String, SteamPackItem> steamPackItemMap = steamPackItems.getMap();

//        Scanner sc = new Scanner(System.in);
        // 上架商品
        for (TradeStateItem tradeStateItem : tradeStateItems) {
            SteamPackItem steamPackItem = steamPackItemMap.get(tradeStateItem.getSteamName());
//            System.out.print(steamPackItem+"是否出售:");
//            if(!sc.nextLine().equals("Y"))
//                continue;
            // 在steam背包中找不到物品
            if (steamPackItem == null) {
                logger.error("steam仓库找不到物品：" + tradeStateItem.getSteamName());
                continue;
            }
            // 获取最低的税后售价
            BigDecimal minPirce = steamBot.getMinFeePrice(steamService.getInfoBySteamName(tradeStateItem.getSteamName()).getId());
            // 出售
            SteamSellState sellState = steamBot.sell(steamPackItem, minPirce);
            if (sellState.getGoodsState() == GoodsState.SELLING || sellState.getGoodsState() == GoodsState.CONFIRMING) {
                logger.info(tradeStateItem.getSteamName() + " 已上架 " + sellState.getSellID() + " 价格"+minPirce);
                // 把状态写入数据库
                tradeService.updateState(tradeStateItem.getId(), sellState.getGoodsState(), minPirce,sellState.getSellID());
            } else {
                logger.error(steamPackItem.getSteamName() + "上架失败：" + sellState);
            }

        }
    }

    // 检查确认状态
    public void checkConfirm() {
        TradeStateItems tradeStateItems = tradeService.listTradeStateItem(GoodsState.CONFIRMING);
        HashMap<String, SteamSellingItem> confirmItemMap = steamBot.getConfirmItems().getIDMap();
        HashMap<String, SteamSellingItem> sellingItemMap = steamBot.getSellingItems().getIDMap();
        List<TradeStateItem> search = new ArrayList<>();
        for (TradeStateItem tradeStateItem : tradeStateItems) {
            // 在待确认列表中找到商品
            SteamSellingItem confirmItem = confirmItemMap.get(tradeStateItem.getSellId());
            if (confirmItem != null) {
                long confirgTime = System.currentTimeMillis() - tradeStateItem.getTime().getTime();
                if (confirgTime > 60 * 5 * 1000) {
                    logger.warn(tradeStateItem.getSteamName() + "仍在确认，确认时间：" + (confirgTime / 1000) / 60 + "分钟");
                    boolean success = steamBot.unsell(confirmItem);
                    if (success){
                        tradeService.updateState(tradeStateItem.getId(), GoodsState.PACKAGE);
                        logger.info(tradeStateItem.getSteamName() + " 已被下架");
                    }
                    else {
                        logger.error(tradeStateItem.getSteamName() + " 下架失败");
                    }
                }
                // 在销售列表中找到商品
            } else if (sellingItemMap.get(tradeStateItem.getSellId()) != null) {
                logger.info(tradeStateItem.getSteamName() + "已被确认上架");
                // 更新为待出售状态
                tradeService.updateState(tradeStateItem.getId(), GoodsState.SELLING);
            }
            // 在确认列表和销售列表中都找不到该商品
            else {
                search.add(tradeStateItem);
            }
        }
        if (search.size() > 0) {
            logger.info("历史交易中搜索记录：" + search.size());
            SteamTradeHistorys tradeHistoryItems = steamBot.getTradeHistoryByTime(System.currentTimeMillis() - search.get(0).getTime().getTime());
            HashMap<String, SteamTradeHistory> IDMap = tradeHistoryItems.getIDMap();
            for (TradeStateItem tradeStateItem : search) {
                SteamTradeHistory tradeHistoryItem = IDMap.get(tradeStateItem.getSellId());
                if (tradeHistoryItem == null) {
                    logger.error(tradeStateItem.getSteamName() + "处于待确认状态，但历史交易记录中找不到记录");
                } else {
                    if (tradeHistoryItem.getGoodsState() == GoodsState.SUCCESS) {
                        tradeService.updateState(tradeStateItem.getId(), GoodsState.SUCCESS);
                        logger.info(tradeStateItem.getSteamName() + "已出售");
                    } else if (tradeHistoryItem.getGoodsState() == GoodsState.PACKAGE) {
                        tradeService.updateState(tradeStateItem.getId(), GoodsState.PACKAGE);
                        logger.error(tradeStateItem.getSteamName() + "被意外下架");
                    } else {
                        logger.error(tradeHistoryItem.getSteamName() + "状态未知：" + tradeHistoryItem);
                    }
                }

            }
        }
    }

    public void checkSell() { // 检查出售状态
        List<TradeStateItem> tradeStateItems = tradeService.listTradeStateItem(GoodsState.SELLING);
        SteamSellingItems steamSellingItems = steamBot.getSellingItems();
        sellingIDMap = steamSellingItems.getIDMap();
        List<TradeStateItem> search = new ArrayList<>();
        for (TradeStateItem tradeStateItem : tradeStateItems) {
            SteamSellingItem steamSellingItem = sellingIDMap.get(tradeStateItem.getSellId());
            // 在销售列表中找不到商品
            if (steamSellingItem == null) {
                search.add(tradeStateItem);
            }
            // 找到商品
            else {
                checkPrice(steamSellingItem, tradeStateItem);
            }
        }

        if (search.size() >= 1) {
            checkHistory(search);
        }
    }

    // 在操作历史中搜索商品
    public void checkHistory(List<TradeStateItem> search) {
        SteamTradeHistorys tradeHistoryItems = steamBot.getTradeHistoryByTime(System.currentTimeMillis() - search.get(0).getTime().getTime() + 60 * 60 * 1000);
        HashMap<String, SteamTradeHistory> historIDMap = tradeHistoryItems.getIDMap();
        // 历史交易记录中搜索状态
        for (TradeStateItem tradeStateItem : search) {
            SteamTradeHistory steamTradeHistory = historIDMap.get(tradeStateItem.getSellId());
            if (steamTradeHistory == null) {
                logger.error(tradeStateItem.getSteamName() + "处于待出售状态，历史交易记录中找不到记录");
            } else {
                if (steamTradeHistory.getGoodsState() == GoodsState.SUCCESS) {
                    boolean success = tradeService.updateState(tradeStateItem.getId(), GoodsState.SUCCESS);
                    if(!success) {
                        logger.error("数据库出售状态更新失败");
                    }
                    else {
                        logger.info(tradeStateItem.getSteamName() + "已出售");
                    }
                } else if (steamTradeHistory.getGoodsState() == GoodsState.SELLING) {
                } else if (steamTradeHistory.getGoodsState() == GoodsState.PACKAGE) {
                    logger.error(tradeStateItem.getSteamName() + "被意外下架");
                    // 尚未找到意外下架的原因，该语句为拆东墙补西墙
                    tradeService.updateState(tradeStateItem.getId(), GoodsState.PACKAGE);
                } else {
                    logger.error(tradeStateItem.getSteamName() + "状态未知：" + steamTradeHistory);
                }
            }
        }
    }


    @Deprecated
    public void reSell(SteamSellingItem steamSellingItem, TradeStateItem tradeStateItem, double price) {
        reSell(steamSellingItem, tradeStateItem, new BigDecimal(price+""));
    }

    public void reSell(SteamSellingItem steamSellingItem, TradeStateItem tradeStateItem, BigDecimal price) {
        sellingIDMap = steamBot.getSellingItems().getIDMap();
        if (sellingIDMap.get(tradeStateItem.getSellId()) != null) {
            // 下架成功
            if (steamBot.unsell(steamSellingItem)) {
                logger.info(tradeStateItem.getSteamName() + " 下架成功，正在重新上架");
                tradeService.updateState(tradeStateItem.getId(), GoodsState.PACKAGE);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                SteamPackItems steamPackItems;
                int error = 0;
                while (true) {
                    try {
                        steamPackItems = steamBot.getPack();
                        break;
                    } catch (NetworkException e) {
                        logger.error(e);
                        try {
                            Thread.sleep(3000 * ++error);
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
                HashMap<String, SteamPackItem> steamPackItemMap = steamPackItems.getMap();
                SteamPackItem steamPackItem = steamPackItemMap.get(tradeStateItem.getSteamName());
                if (steamPackItem != null) {
                    try {
                        SteamSellState sellState = steamBot.sell(steamPackItem, price);
                        if (sellState.getGoodsState() == GoodsState.SELLING || sellState.getGoodsState() == GoodsState.CONFIRMING) {
                            logger.info(steamPackItem.getSteamName() + "上架成功");
                            tradeService.updateState(tradeStateItem.getId(), sellState.getGoodsState(), price, sellState.getSellID());
                        } else {
                            logger.error("上架失败" + sellState);
                        }
                    }catch (NetworkException e){
                        logger.error(e);
                        // 上架发生网络异常时候进行处理
                        sellNetworkException(steamPackItem.getSteamName());
                    }

                } else {
                    logger.error(tradeStateItem.getSteamName() + " 重新上架失败 " + "背包找不到物品");
                }
            }
        }
    }

    private void sellNetworkException(String steamName){
        // 检查是否存在于确认列表
        SteamSellingItems confirmItems = steamBot.getConfirmItems();
        for(SteamSellingItem sellingItem : confirmItems){
            if (sellingItem.getSteamName().equals(steamName)){
                steamBot.unsell(sellingItem);
                return;
            }
        }
        SteamPackItems pack = steamBot.getPack();
        HashMap<String, SteamPackItem> packMap = pack.getMap();
        // 检查饰品是否还存在于背包
        if(packMap.get(steamName)==null){
            SteamSellingItems sellingItems = steamBot.getSellingItems();
            for(SteamSellingItem steamSellingItem : sellingItems){
                String locSteamName = steamSellingItem.getSteamName();
                if (locSteamName.equals(steamName)){
                    steamBot.unsell(steamSellingItem);
                    break;
                }
            }
        }
    }


    public void checkPrice(SteamSellingItem steamSellingItem, TradeStateItem tradeStateItem) {
        PriceNum[] priceNums = steamBot.getMinPrices(steamService.getInfoBySteamName(steamSellingItem.getSteamName()).getId());
        if (priceNums == null) {
            return;
        }
        BigDecimal feePrice = priceNums[0].getFeePrice();
//        System.out.println(feePrice);
        if (priceNums[0].getFeePrice().compareTo(steamSellingItem.getPrice())<0 || System.currentTimeMillis() - tradeStateItem.getTime().getTime() > 60 * 60 * 9 * (long) 1000) {
            long hasBuyedTime = System.currentTimeMillis() - tradeStateItem.getBuyTime().getTime();
            if (hasBuyedTime> 60*60*24*7*1000||(feePrice.subtract(new BigDecimal("0.01"))).divide(new BigDecimal(tradeStateItem.getBuyPrice()+""), 2, BigDecimal.ROUND_HALF_DOWN).compareTo(new BigDecimal("1.45")) > 0) {
                logger.info(tradeStateItem.getSteamName() + " 价格需要降低为：" + (feePrice.subtract(new BigDecimal("0.01"))));
                reSell(steamSellingItem, tradeStateItem, feePrice.subtract(new BigDecimal("0.01")));
            } else {
                logger.warn(tradeStateItem.getSteamName() + " 价格不是最低且降低后利润过少");
            }
        } else if (priceNums[0].getFeePrice().compareTo(steamSellingItem.getPrice()) == 0 && priceNums[0].getNum() == 1) {
            if (priceNums[1].getFeePrice().subtract(steamSellingItem.getPrice()).compareTo(new BigDecimal("0.01")) > 0) {
                logger.info(tradeStateItem.getSteamName() + "可提高价格");
                reSell(steamSellingItem, tradeStateItem, priceNums[1].getFeePrice().subtract(new BigDecimal("0.01")));
            }
        } else if (priceNums[0].getFeePrice().compareTo(steamSellingItem.getPrice()) > 0) {
            logger.error(tradeStateItem.getSteamName() + " 商品最低价大于出售价格？？？");
        }
    }


    @Override
    public void run() {
        while (true) {
            try {
                logger.info("开始上架商品");
                steamSell();
                logger.info("检查确认状态");
                checkConfirm();
                logger.info("检查出售状态");
                checkSell();
                logger.info("执行完毕！");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    Thread.sleep(60 * 1 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        AutoSell autoSell = new AutoSell();
        autoSell.run();
    }
}
